package com.example.monitor.utils;

import com.example.monitor.model.*;
import oshi.SystemInfo;
import oshi.hardware.*;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.RuntimeMXBean;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * getCpuInfo()- 获取CPU信息
 * getMemInfo()- 获取内存信息
 * getJvmInfo()- 获取JVM信息
 * getSysInfo()- 获取系统信息
 * getSysFileInfo()- 获取文件系统信息
 * getRedisInfo()- 获取Redis信息（需要额外实现）
 * getAllInfo()- 获取所有系统信息
 */
public class ServerUtil {
    private static final SystemInfo SYSTEM_INFO = new SystemInfo();
    private static final HardwareAbstractionLayer HARDWARE = SYSTEM_INFO.getHardware();
    private static final OperatingSystem OS = SYSTEM_INFO.getOperatingSystem();

    // CPU ticks缓存，用于计算使用率
    private static long[] prevCpuTicks;

    /**
     * 获取CPU信息
     */
    public static CpuEntity getCpuInfo() {
        CentralProcessor processor = HARDWARE.getProcessor();
        CpuEntity cpu = new CpuEntity();

        // 设置基本信息
        cpu.setName(processor.getProcessorIdentifier().getName());
        cpu.setPhysicalCount(processor.getPhysicalProcessorCount());
        cpu.setLogicalCount(processor.getLogicalProcessorCount());

        // 计算CPU使用率
        if (prevCpuTicks == null) {
            prevCpuTicks = processor.getSystemCpuLoadTicks();
            Util.sleep(1000);
        }

        long[] ticks = processor.getSystemCpuLoadTicks();
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] -
                prevCpuTicks[CentralProcessor.TickType.USER.getIndex()];
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] -
                prevCpuTicks[CentralProcessor.TickType.NICE.getIndex()];
        long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] -
                prevCpuTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] -
                prevCpuTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] -
                prevCpuTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long total = user + nice + sys + idle + iowait;

        if (total > 0) {
            cpu.setUserUsage(toBigDecimal(100.0 * user / total));
            cpu.setSystemUsage(toBigDecimal(100.0 * sys / total));
            cpu.setIdleRate(toBigDecimal(100.0 * idle / total));
            cpu.setIoWaitRate(toBigDecimal(100.0 * iowait / total));
            cpu.setTotalUsage(toBigDecimal(100.0 * (user + nice + sys) / total));
        }

        // 设置频率信息
        long[] currentFreq = processor.getCurrentFreq();
        if (currentFreq != null && currentFreq.length > 0) {
            cpu.setCurrentFreq(currentFreq[0]);
        }

        cpu.setMaxFreq(processor.getMaxFreq());

        // 设置上下文切换和中断信息
        cpu.setContextSwitches(processor.getContextSwitches());
        cpu.setInterrupts(processor.getInterrupts());

        // 更新缓存
        prevCpuTicks = ticks;

        return cpu;
    }

    /**
     * 获取内存信息
     */
    public static MemEntity getMemInfo() {
        GlobalMemory memory = HARDWARE.getMemory();
        MemEntity mem = new MemEntity();

        // 物理内存信息
        long physicalTotal = memory.getTotal();
        long physicalAvailable = memory.getAvailable();
        long physicalUsed = physicalTotal - physicalAvailable;

        mem.setPhysicalTotal(physicalTotal);
        mem.setPhysicalUsed(physicalUsed);
        mem.setPhysicalFree(physicalAvailable);
        mem.setPhysicalUsage(toBigDecimal(100.0 * physicalUsed / physicalTotal));

        // 虚拟内存/交换空间信息
        VirtualMemory virtualMemory = memory.getVirtualMemory();
        long swapTotal = virtualMemory.getSwapTotal();
        long swapUsed = virtualMemory.getSwapUsed();
        long swapFree = swapTotal - swapUsed;

        mem.setSwapTotal(swapTotal);
        mem.setSwapUsed(swapUsed);
        mem.setSwapFree(swapFree);
        if (swapTotal > 0) {
            mem.setSwapUsage(toBigDecimal(100.0 * swapUsed / swapTotal));
        }

        // 页大小
        mem.setPageSize(memory.getPageSize());

        return mem;
    }

    /**
     * 获取JVM信息
     */
    public static JvmEntity getJvmInfo() {
        JvmEntity jvm = new JvmEntity();
        RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();

        // 基本信息
        jvm.setName(System.getProperty("java.vm.name"));
        jvm.setVersion(System.getProperty("java.version"));
        jvm.setVendor(System.getProperty("java.vendor"));

        // 启动时间和运行时长
        jvm.setStartTime(formatTimestamp(runtimeBean.getStartTime()));
        jvm.setRunTime(runtimeBean.getUptime());

        // 堆内存信息
        jvm.setHeapInit(memoryBean.getHeapMemoryUsage().getInit());
        jvm.setHeapMax(memoryBean.getHeapMemoryUsage().getMax());
        jvm.setHeapUsed(memoryBean.getHeapMemoryUsage().getUsed());
        jvm.setHeapCommitted(memoryBean.getHeapMemoryUsage().getCommitted());

        // 非堆内存信息
        jvm.setNonHeapInit(memoryBean.getNonHeapMemoryUsage().getInit());
        jvm.setNonHeapMax(memoryBean.getNonHeapMemoryUsage().getMax());
        jvm.setNonHeapUsed(memoryBean.getNonHeapMemoryUsage().getUsed());
        jvm.setNonHeapCommitted(memoryBean.getNonHeapMemoryUsage().getCommitted());

        // 内存使用率
        long heapMax = memoryBean.getHeapMemoryUsage().getMax();
        long heapUsed = memoryBean.getHeapMemoryUsage().getUsed();
        if (heapMax > 0) {
            jvm.setMemoryUsage(toBigDecimal(100.0 * heapUsed / heapMax));
        }

        // 类加载信息
        jvm.setLoadedClassCount(ManagementFactory.getClassLoadingMXBean().getLoadedClassCount());
        jvm.setTotalLoadedClassCount(ManagementFactory.getClassLoadingMXBean().getTotalLoadedClassCount());
        jvm.setUnloadedClassCount(ManagementFactory.getClassLoadingMXBean().getUnloadedClassCount());

        // 线程信息
        jvm.setThreadCount(ManagementFactory.getThreadMXBean().getThreadCount());
        jvm.setPeakThreadCount(ManagementFactory.getThreadMXBean().getPeakThreadCount());
        jvm.setDaemonThreadCount(ManagementFactory.getThreadMXBean().getDaemonThreadCount());

        return jvm;
    }

    /**
     * 获取系统信息
     */
    public static SysEntity getSysInfo() {
        SysEntity sys = new SysEntity();
        ComputerSystem computerSystem = HARDWARE.getComputerSystem();

        // 服务器基本信息
        try {
            sys.setComputerName(InetAddress.getLocalHost().getHostName());
            sys.setComputerIp(InetAddress.getLocalHost().getHostAddress());
        } catch (UnknownHostException e) {
            sys.setComputerName("Unknown");
            sys.setComputerIp("Unknown");
        }

        // 操作系统信息
        sys.setOsName(OS.toString());
        sys.setOsArch(System.getProperty("os.arch"));
        sys.setOsVersion(OS.getVersionInfo().getVersion());

        // 启动时间和运行时长
        long bootTime = OS.getSystemBootTime() * 1000L;
        sys.setBootTime(formatTimestamp(bootTime));
        sys.setUptime(System.currentTimeMillis() - bootTime);

        // 用户信息
        sys.setUser(OS.getCurrentProcess().getUser());

        // 进程和线程信息
        sys.setProcessCount(OS.getProcessCount());
        sys.setThreadCount(OS.getThreadCount());

        // 系统负载
        double[] loadAverage = HARDWARE.getProcessor().getSystemLoadAverage(3);
        if (loadAverage != null && loadAverage.length >= 3) {
            sys.setSystemLoad1(toBigDecimal(loadAverage[0]));
            sys.setSystemLoad5(toBigDecimal(loadAverage[1]));
            sys.setSystemLoad15(toBigDecimal(loadAverage[2]));
        }

        // 硬件信息
        sys.setManufacturer(computerSystem.getManufacturer());
        sys.setModel(computerSystem.getModel());
        sys.setSerialNumber(computerSystem.getSerialNumber());
        sys.setFirmwareVersion(computerSystem.getFirmware().getVersion());

        // 网络接口信息
        List<NetworkIF> nets = HARDWARE.getNetworkIFs();
        List<SysEntity.NetworkInterfaceInfo> networkInterfaces = new ArrayList<>();

        for (NetworkIF net : nets) {
            SysEntity.NetworkInterfaceInfo info = new SysEntity.NetworkInterfaceInfo();
            info.setName(net.getName());
            info.setDisplayName(net.getDisplayName());
            info.setMac(net.getMacaddr());

            String[] ipv4 = net.getIPv4addr();
            if (ipv4 != null && ipv4.length > 0) {
                info.setIpv4(String.join(", ", ipv4));
            }

            String[] ipv6 = net.getIPv6addr();
            if (ipv6 != null && ipv6.length > 0) {
                info.setIpv6(String.join(", ", ipv6));
            }

            info.setBytesRecv(net.getBytesRecv());
            info.setBytesSent(net.getBytesSent());
            info.setPacketsRecv(net.getPacketsRecv());
            info.setPacketsSent(net.getPacketsSent());

            networkInterfaces.add(info);
        }

        sys.setNetworkInterfaces(networkInterfaces);

        return sys;
    }

    /**
     * 获取文件系统信息
     */
    public static List<SysFileEntity> getSysFileInfo() {
        List<SysFileEntity> files = new ArrayList<>();
        List<HWDiskStore> diskStores = HARDWARE.getDiskStores();

        for (HWDiskStore disk : diskStores) {
            for (HWPartition partition : disk.getPartitions()) {
                SysFileEntity file = new SysFileEntity();

                file.setDirName(partition.getMountPoint());
                file.setTypeName(partition.getType());
                file.setTotal(partition.getSize());

                // 获取分区使用情况
                OSFileStore store = null;
                for (OSFileStore fs : OS.getFileSystem().getFileStores()) {
                    if (fs.getMount().equals(partition.getMountPoint())) {
                        store = fs;
                        break;
                    }
                }

                if (store != null) {
                    long totalSpace = store.getTotalSpace();
                    long freeSpace = store.getFreeSpace();
                    long usedSpace = totalSpace - freeSpace;

                    file.setTotal(totalSpace);
                    file.setUsed(usedSpace);
                    file.setFree(freeSpace);

                    if (totalSpace > 0) {
                        file.setUsage(toBigDecimal(100.0 * usedSpace / totalSpace));
                    }

                    file.setUsable(freeSpace > 0);
                    file.setMountPoint(store.getMount());
                    file.setOptions(store.getOptions());
                }

                // 磁盘IO信息
                file.setDiskReads(disk.getReads());
                file.setDiskWrites(disk.getWrites());
                file.setReadBytes(disk.getReadBytes());
                file.setWriteBytes(disk.getWriteBytes());

                if (disk.getReads() > 0 || disk.getWrites() > 0) {
                    file.setQueue((double) disk.getCurrentQueueLength());
                    file.setServiceTime(disk.getTransferTime() / (double) (disk.getReads() + disk.getWrites()));
                }

                files.add(file);
            }
        }

        return files;
    }

//    /**
//     * 获取Redis信息（需要额外依赖和配置）
//     */
//    public static RedisEntity getRedisInfo() {
//        RedisEntity redis = new RedisEntity();
//
//        // 这里需要根据实际Redis连接配置实现
//        // 以下为模拟数据，实际应用中应该通过Jedis等客户端获取
//
//        redis.setVersion("6.2.6");
//        redis.setMode("standalone");
//        redis.setUptime(86400L);
//        redis.setConnectedClients(5);
//        redis.setBlockedClients(0);
//        redis.setUsedMemory(1048576L);
//        redis.setMemFragmentationRatio(toBigDecimal(1.2));
//        redis.setTotalCommandsProcessed(1000L);
//        redis.setInstantaneousOpsPerSec(10L);
//        redis.setKeyspaceHits(500L);
//        redis.setKeyspaceMisses(50L);
//
//        Map<String, Integer> keyspace = new HashMap<>();
//        keyspace.put("db0", 100);
//        keyspace.put("db1", 50);
//        redis.setKeyspace(keyspace);
//
//        redis.setIsRunning(true);
//        redis.setLastError("None");
//
//        return redis;
//    }

    /**
     * 获取所有系统信息
     */
    public static Map<String, Object> getAllInfo() {
        Map<String, Object> info = new HashMap<>();
        info.put("cpu", getCpuInfo());
        info.put("memory", getMemInfo());
        info.put("jvm", getJvmInfo());
        info.put("system", getSysInfo());
        info.put("files", getSysFileInfo());
//        info.put("redis", getRedisInfo());

        return info;
    }

    /**
     * 辅助方法：将double转换为BigDecimal，保留2位小数
     */
    private static BigDecimal toBigDecimal(double value) {
        return BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 辅助方法：格式化时间戳
     */
    private static String formatTimestamp(long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault())
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
}
